//=========================================================
// File			- macros.h
// Author		- Jesse Lampert
// Created	- 12/09/05
//=========================================================

#ifndef __MACROS_H
#define __MACROS_H

//=== Macros ==============================================
//=========================================================
// Macro    - FIXED_POINT
// Author   - Jesse Lampert
// Purpose  - convert a constant float value to a fixed point number
//=========================================================
#define FIXED_POINT( float ) ( (f32)( (int32)( ( ( 1 << F32_BITS ) * (float) ) ) ) )

//=========================================================
// Macro    - FUNCTION_NAME
// Author   - Jesse Lampert
// Purpose  - get a function's name
//=========================================================
#ifdef AEE_SIMULATOR
	#define FUNCTION_NAME __FUNCTION__
#else
	#define FUNCTION_NAME __func__
#endif

//=========================================================
// Macro    - START_PACKED_STRUCT
// Author   - Jesse Lampert
// Purpose  - packs a struct for 1 byte alignment
//=========================================================
#ifdef AEE_SIMULATOR
	#define START_PACKED_STRUCT	__pragma( pack( push, 1) )
#else
	#define START_PACKED_STRUCT __packed
#endif

//=========================================================
// Macro    - END_PACKED_STRUCT
// Author   - Jesse Lampert
// Purpose  - closes packing for structs
//=========================================================
#ifdef AEE_SIMULATOR
	#define END_PACKED_STRUCT	__pragma( pack( pop ) )
#else
	#define END_PACKED_STRUCT
#endif

//=========================================================
// Macro    - FIX_INT
// Author   - Jesse Lampert
// Purpose  - convert a fixed value to an int16 value
//=========================================================
#define FIX_INT( fixed ) ( (int16)( (fixed) >> F32_BITS ) )

//=========================================================
// Macro    - INT_FIX
// Author   - Jesse Lampert
// Purpose  - convert a fixed value to an int value
//=========================================================
#define INT_FIX( int ) ( (int32)( (int) << F32_BITS ) )

//=========================================================
// Macro    - ZERO_OBJECT
// Author   - Jesse Lampert
// Purpose  - zero memory from within an object
//=========================================================
#define ZERO_OBJECT( object ) MEMSET( (void *)&object, 0, sizeof( object ) )

//=========================================================
// Macro    - INTERPOLATE
// Author   - Jesse Lampert
//=========================================================
#define INTERPOLATE( begin, end, numerator, denominator ) \
	( (begin) + (((end) - (begin)) * (numerator)) / (denominator) )

//=========================================================
// Macro    - IS_SELECT
// Author   - Jesse Lampert
// Purpose  - figures out if a pressed KEY is a selection
//=========================================================
#define IS_SELECT( key ) \
	( ( (key) & KEY_OK ) || ( (key) & KEY_5 ) )

//=========================================================
// Macro    - NUM_ELEMENTS
// Author   - Jesse Lampert
// Purpose  - calculate the number of elements in a fixed array
//=========================================================
#define NUM_ELEMENTS( array ) ( sizeof( array ) / sizeof( array[0] ) )

//=========================================================
// Macro    - TEST_FLAG
// Author   - Jesse Lampert
// Purpose  - test a single bit in a flag
//=========================================================
#define TEST_FLAG( flags, bit ) ( (flags) & ( 1 << (bit) ) )

//=========================================================
// Macro    - TEST_FLAG
// Author   - Jesse Lampert
// Purpose  - test a single bit in a flag
//=========================================================
#define SET_FLAG( flags, bit ) ( (flags) |= ( 1 << (bit) ) )

//=========================================================
// Macro    - CLAMP
// Author   - Jesse Lampert
// Purpose  - clamp a value within a range
//=========================================================
#define CLAMP( val, min, max )	\
	(val) = ( ( (val) < (min) ? (min) : (val) > (max) ? (max) : (val) ) )

//=========================================================
// Macro    - CLAMP_HIGH
// Author   - Jesse Lampert
// Purpose  - clamp a value to an upper bound
//=========================================================
#define CLAMP_HIGH( val, max )	(val) = ( (val) > (max) ? (max) : (val) )

//=========================================================
// Macro    - CLAMP_LOW
// Author   - Jesse Lampert
// Purpose  - clamp a value to a lower bound
//=========================================================
#define CLAMP_LOW( val, min )		(val) = ( (val) < (min) ? (min) : (val) )

//=========================================================
// Macro    - TRANSLATE
// Author   - Jesse Lampert
// Purpose  - translate a value towards a destination
//						and clamp to it
//=========================================================
#define TRANSLATE( val, amount, dest )	\
	(val) = (val) < (dest) ? ( (val) + (amount) > (dest) ? (dest) : (val) + (amount) ) :		\
	( (val) > (dest) ? ( (val) - (amount) < (dest) ? (dest) : (val) - (amount) ) : (val) )

//=========================================================
// Macro    - REPORT_MEMORY
// Author   - Jesse Lampert
// Purpose  - reports the current free memory
//=========================================================
#define REPORT_MEMORY( ) DDD( ( "%s - %d Heap: %d", FUNCTION_NAME, __LINE__, GETRAMFREE( NULL, NULL ) ) )

//=========================================================
// Macro    - UPDATE_TIMER
// Author   - Jesse Lampert
// Purpose  - countdown an unsigned timer to 0
//=========================================================
#define UPDATE_TIMER( unsignedMS, elapseMS )	\
	( unsignedMS ) = ( ( (elapseMS) >= (unsignedMS) ) ? 0 : (unsignedMS) - (elapseMS) )

//=========================================================
// Macro    - for_each
// Author   - Jesse Lampert
// Purpose  - dirty foreach macro
//=========================================================
#define for_each( type, iterator, container, count )	\
	for( type * iterator = container; iterator < container + count; ++iterator )

#endif // __MACROS_H